package com.msgserver.mbeans;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import org.primefaces.component.dialog.Dialog;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;
import org.slf4j.LoggerFactory;

import com.msgserver.ejb.services.CompanyService;
import com.msgserver.ejb.services.CompanyServiceLocal;
import com.msgserver.entity.Company;
import com.msgserver.entity.Employee;
import com.msgserver.entity.EmployeeGroup;
import com.msgserver.utils.MsgServerUtils;

@ManagedBean
@ViewScoped
public class MsgAdminBean {
	public MsgAdminBean(){
		
	}
	
	@ManagedProperty(value = "#{globalBean}")
	private GlobalBean gBean;
	@EJB(mappedName="MsgServer_EAR/CompanyService/local-com.msgserver.ejb.services.CompanyServiceLocal")
	private CompanyServiceLocal companyService;
	private List<Employee> selectedEmps = new ArrayList<Employee>();
	private List<SelectItem> groupsItems = new ArrayList<SelectItem>();
	private SelectItem selectedItem;
	private Long selectedGroupId;
	private String newGroupName;
	private Company company;
	private EmployeeGroup currentGroup;
	private Integer numberOfItemsInCurrentGroup;
	private String newUserName;
	private String newUserPhone;
	private String searchKeyWord;
	private List<Employee> searchResultEmp = new ArrayList<Employee>();
	private Employee[] selectedEmpsInSearchResult;
	private Logger logger;
	
	private Employee[] selectedEmpsInTbl;
	
	private Dialog uploadDialog;
	
	@PostConstruct
	private void init(){
		company = gBean.getAdmin().getCompany();
		logger = Logger.getLogger(this.getClass());
		buildGroupItems();
		setCurrentGroup(company.getGroups().iterator().next());
		for(Employee emp:getCurrentGroup().getEmployee()){
			getSelectedEmps().add(emp);
		}
	}
	
	public void addNewGroup(){
		String name = getNewGroupName();
		EmployeeGroup newGroup =new EmployeeGroup();
		newGroup.setName(name);
		newGroup.setCompany(company);
		company.getGroups().add(newGroup);
		company = companyService.persistCompany(company);
		buildGroupItems();
	}
	
	public void deleteSelectedEmps(){
		Employee[] empsToDel = getSelectedEmpsInTbl();
		deleteEmps(empsToDel);
	}
	
	private void deleteEmps(Employee[] empsToDel){
		List<Employee> empWithoutGroups = new ArrayList<Employee>();
		for(Employee emp : empsToDel){
			getSelectedEmps().remove(emp);
			currentGroup.getEmployee().remove(emp);
			if(isOnlyBelongsToThisGroup(currentGroup, emp)){
				empWithoutGroups.add(emp);
			}
		}
		currentGroup = companyService.persistGroup(currentGroup);
		if(!empWithoutGroups.isEmpty()){
			companyService.deleteEmps(empWithoutGroups);
		}
	}
	
	public void deleteSelectedGroup(ActionEvent e){
		Long id = (Long) e.getComponent().getAttributes().get("selectedGroupInTree");
		List<Employee> empsToDel = new ArrayList<Employee>();
		currentGroup = getGroupById(id);
		company.getGroups().remove(currentGroup);
		
		company = companyService.persistCompany(company);
		for(Employee emp:currentGroup.getEmployee()){
			if(isOnlyBelongsToThisGroup(currentGroup, emp)){
				empsToDel.add(emp);
			}
		}
		if(!empsToDel.isEmpty()){
			companyService.deleteEmps(empsToDel);
		}
		buildGroupItems();
		setCurrentGroup(null);
	}
	
	public void addNewContactToCurrentGroup(){
		String name = getNewUserName();
		String phone = getNewUserPhone();
		Employee emp = new Employee();
		emp.setName(name);
		emp.setPhoneNumber(phone);
		getCurrentGroup().getEmployee().add(emp);
		//getSelectedEmps().add(0, emp);
		currentGroup = companyService.persistGroup(currentGroup);
		updateCompanyData(currentGroup);
		//rebuild the current table data
		rebuildCurrentTbl();
		FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"添加联系人成功",emp.getName()));
	}
	
	private void rebuildCurrentTbl(){
		getSelectedEmps().clear();
		getSelectedEmps().addAll(currentGroup.getEmployee());
	}
	
	public void searchEmp(){
		getSearchResultEmp().clear();
		if(getSearchKeyWord() != null || getSearchKeyWord().trim() != ""){
			String key = getSearchKeyWord();
			if(!MsgServerUtils.isNum(key)){
				for(Employee emp:getCurrentGroup().getEmployee()){
					if(emp.getName().equals(key)){
						searchResultEmp.add(emp);
					}
				}
			}else{
				for(Employee emp:getCurrentGroup().getEmployee()){
					if(emp.getPhoneNumber().equals(key)){
						searchResultEmp.add(emp);
					}
				}
			}
		}
		if(searchResultEmp.isEmpty()){
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,"无匹配搜索结果",null));

		}
	}
	
	public void editEmp(){
		List<Employee> emps = getSearchResultEmp();
		for(Employee editedEmps : emps){
			for(Employee emp :getCurrentGroup().getEmployee()){
				if(editedEmps.getUid().equals(emp.getUid())){
					getCurrentGroup().getEmployee().remove(emp);
					getCurrentGroup().getEmployee().add(companyService.updateEmp(editedEmps));
					break;
				}
			}
		}
		rebuildCurrentTbl();
	}
	
	public void initSearchForm(){
		setSearchKeyWord(null);
		getSearchResultEmp().clear();
		setSelectedEmpsInSearchResult(null);
	}
	
	public void deleteEmpAfterSearch(){
		Employee[] empsTodel = getSelectedEmpsInSearchResult();
		deleteEmps(empsTodel);
	}
	
	private boolean isOnlyBelongsToThisGroup(EmployeeGroup group, Employee emp){
		Set<EmployeeGroup> groupsForThisEmp = emp.getGroups();
		groupsForThisEmp.remove(currentGroup);
		if(groupsForThisEmp.isEmpty()){
			return true;
		}
		return false;
	}
	
	private void buildGroupItems(){
		getGroupsItems().clear();
		Set<EmployeeGroup> groups = company.getGroups();
		for(EmployeeGroup group : groups){
			SelectItem item = new SelectItem();
			item.setLabel(group.getName());
			item.setValue(group.getId());
			getGroupsItems().add(item);
		}
	}
	public void fileUploadListener(FileUploadEvent event) throws IOException{
		UploadedFile file = event.getFile();
		String fileName = file.getFileName();
		String fileExtension = fileName.substring(fileName.indexOf(".")+1);
		List<Employee> uploadedEmps = new ArrayList<Employee>();
		if(fileExtension.equalsIgnoreCase("xls")){
			uploadedEmps = MsgServerUtils.readExcel(file);
			selectedEmps.addAll(uploadedEmps);
		
		}else if(fileExtension.equalsIgnoreCase("txt")){
			logger.info("txt file "+fileName +" has been uploaded");
			List<String> uploaded = MsgServerUtils.readText(file);
			for(String s : uploaded){
				Employee emp = new Employee();
				emp.setName("");
				emp.setPhoneNumber(s);
				uploadedEmps.add(emp);
			}
			selectedEmps.addAll(uploadedEmps);
		}
		if(currentGroup !=null){
        	currentGroup.getEmployee().addAll(selectedEmps);
        	currentGroup = companyService.persistGroup(currentGroup);
        	updateCompanyData(currentGroup);
         	//company = companyService.persistCompany(company);
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,fileExtension+"上传成功！","成功上传 "+uploadedEmps.size()+" 个号码"));
			logger.info(fileExtension+" file "+event.getFile().getFileName()+" has been uploaded");
         }
	}
	
	public void getSelectedGroupInTree(ActionEvent e){
		Long id = (Long) e.getComponent().getAttributes().get("selectedGroupInTree");
		currentGroup = getGroupById(id);
		getSelectedEmps().clear();
		for(Employee emp: currentGroup.getEmployee()){
			selectedEmps.add(emp);
		}
	}
	
/*	private int getEmpsFromUploadedExcel(HSSFWorkbook wb){
		
         selectedEmps.add(MsgServerUtils.readExcel(file));
        
         if(currentGroup !=null){
        	currentGroup.getEmployee().addAll(selectedEmps);
        	currentGroup = companyService.persistGroup(currentGroup);
        	updateCompanyData(currentGroup);
         	//company = companyService.persistCompany(company);
         }
         return sheetData.size()-1;
	}
	*/
	private void updateCompanyData(EmployeeGroup group){
		for(EmployeeGroup g:company.getGroups()){
    		if(g.getName().equals(group.getName())){
    			company.getGroups().remove(g);
    			company.getGroups().add(group);
    			break;
    		}
    	}
	}
	
	
	/*private Map<String, Integer> getCellPostionsForEmployeeProperties(HSSFRow row){ 
		Iterator cells = row.cellIterator();
		while(cells.hasNext()){
			if()
		}
	}*/
	
	private EmployeeGroup getGroupById(Long id){
		for(EmployeeGroup g:company.getGroups()){
			if(g.getId().equals(id)){
				return g;
			}
		}
		return null;
	}
	
	private boolean checkValidExcelFile(HSSFWorkbook wb){

		try {
			HSSFSheet sheet = wb.getSheetAt(0);
			HSSFRow row = sheet.getRow(1);
			int i = row.getLastCellNum()-row.getFirstCellNum();
			if(i==2){
				return true;
			}
		} catch (Exception e) {
			return false;
		}
		return false;
	}

	public GlobalBean getgBean() {
		return gBean;
	}

	public void setgBean(GlobalBean gBean) {
		this.gBean = gBean;
	}


	public List<Employee> getSelectedEmps() {
		return selectedEmps;
	}

	public void setSelectedEmps(List<Employee> selectedEmps) {
		this.selectedEmps = selectedEmps;
	}

	public Dialog getUploadDialog() {
		return uploadDialog;
	}

	public void setUploadDialog(Dialog uploadDialog) {
		this.uploadDialog = uploadDialog;
	}

	public List<SelectItem> getGroupsItems() {
		return groupsItems;
	}

	public void setGroupsItems(List<SelectItem> groupsItems) {
		this.groupsItems = groupsItems;
	}

	public Long getSelectedGroupId() {
		return selectedGroupId;
	}

	public void setSelectedGroupId(Long selectedGroupId) {
		this.selectedGroupId = selectedGroupId;
	}

	public SelectItem getSelectedItem() {
		return selectedItem;
	}

	public void setSelectedItem(SelectItem selectedItem) {
		this.selectedItem = selectedItem;
	}

	public String getNewGroupName() {
		return newGroupName;
	}

	public void setNewGroupName(String newGroupName) {
		this.newGroupName = newGroupName;
	}

	public Employee[] getSelectedEmpsInTbl() {
		return selectedEmpsInTbl;
	}

	public void setSelectedEmpsInTbl(Employee[] selectedEmpsInTbl) {
		this.selectedEmpsInTbl = selectedEmpsInTbl;
	}

	public EmployeeGroup getCurrentGroup() {
		return currentGroup;
	}

	public void setCurrentGroup(EmployeeGroup currentGroup) {
		this.currentGroup = currentGroup;
	}

	public Integer getNumberOfItemsInCurrentGroup() {
		
		return getSelectedEmps().size();
	}

	public void setNumberOfItemsInCurrentGroup(Integer numberOfItemsInCurrentGroup) {
		this.numberOfItemsInCurrentGroup = numberOfItemsInCurrentGroup;
	}

	public String getNewUserName() {
		return newUserName;
	}

	public void setNewUserName(String newUserName) {
		this.newUserName = newUserName;
	}

	public String getNewUserPhone() {
		return newUserPhone;
	}

	public void setNewUserPhone(String newUserPhone) {
		this.newUserPhone = newUserPhone;
	}

	public String getSearchKeyWord() {
		return searchKeyWord;
	}

	public void setSearchKeyWord(String searchKeyWord) {
		this.searchKeyWord = searchKeyWord;
	}

	public List<Employee> getSearchResultEmp() {
		return searchResultEmp;
	}

	public void setSearchResultEmp(List<Employee> searchResultEmp) {
		this.searchResultEmp = searchResultEmp;
	}

	public Employee[] getSelectedEmpsInSearchResult() {
		return selectedEmpsInSearchResult;
	}

	public void setSelectedEmpsInSearchResult(Employee[] selectedEmpsInSearchResult) {
		this.selectedEmpsInSearchResult = selectedEmpsInSearchResult;
	}

	public Company getCompany() {
		return company;
	}

	public void setCompany(Company company) {
		this.company = company;
	}



	

}
